// 类型推到
let uname;
uname = 1;
uname = 'zhufeng';
uname = null;


let uname2: string = 'zhufeng';
// uname2 = 2;  报错:不能将类型“number”分配给类型“string”。

// 包装对象 wrapper object
// js类型分为两种:原始类型  对象类型


let name2 = 'zhufeng'
// 字符串是没有这个类型的,内部自动帮你包装成对象类型
console.log(name2.toUpperCase());

// ts帮你处理成
// console.log(new String(name2).toUpperCase());
let isOk: boolean = true;

let isOk2: boolean = Boolean(1);
// ts会帮你处理成
// let isOk2: boolean = new Boolean(1)


// 联合类型
let name3: string | number;
// 此处使用了强制断言!，目的是告诉ts,我的name3一定会有值
name3 = 3.1415;
console.log(name3.toFixed(2));
name3 = 'zhufeng';
console.log(name3!.toString());
// 当类型为指定类型中的一个时,就只能限定使用此类型方法。


// 类型断言
let name4: string | number;

console.log((name4! as number).toFixed(2));
console.log((name4! as string).toString());
// 当使用非指定类型时,则会报错
// console.log((name4! as boolean)); 报错:类型 "string | number" 到类型 "boolean" 的转换可能是错误的，因为两种类型不能充分重叠。如果这是有意的，请先将表达式转换为 "unknown"。
// 此时,如果想继续使用此类型表达,可以使用   双重断言
console.log((name4! as any as boolean));
// 现将name4转换为any类型，在转换为boolean类型即可


// 字面量类型&类型字面量


//字面量类型的值 只能是字面量(即‘Up'类型的值 只能为'Up')
// const up:'Up' = 'down' 报错:不能将类型“"down"”分配给类型“"Up"”。
const up: 'UP' = 'UP';
const down: 'DOWN' = 'DOWN';
const first: 1 = 1;
// 字面量类型使用场景:在使用时可以实现类似枚举的效果
type Direction = 'up' | 'down' | 'left' | 'right'
function move(direction: Direction) {
    console.log(direction);
}
move("down") //编辑器会提示Direction中的内容
// move('key') 报错:类型“"key"”的参数不能赋给类型“Direction”的参数。


// 类型字面量
// 声明的类型 与 实例 必须一一对应
type Person = {
    name: string,
    age: number
}

let p1: Person = {
    name: 'zhufeng',
    // 当缺少某一属性时会报错：类型 "{ name: string; }" 中缺少属性 "age"，但类型 "Person" 中需要该属性。
    age: 18
}


// 字符串字面量 和  联合类型
// 字符串字面量
type T1 = '1' | '2' | '3' // 当声明类型为T1时,值只能为 这三个
// let t1:T1 = '4'  报错:不能将类型“"4"”分配给类型“T1”。
let t1: T1 = '1'
// 联合类型
type T2 = string | number | boolean  //联合类型只限定/校验类型,对值并无要求
// let t2: T2 = {}  报错:不能将类型“{}”分配给类型“T2”。